home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / fspdev / fspdevPfs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-19  |  43.8 KB  |  1,250 lines

  1. /*
  2.  * fsPfs.c --
  3.  *
  4.  *    Routines specific to the pseudo-filesystem implementation.
  5.  *    The pseudo-filesystem server uses the same request response
  6.  *    protocol as with pseudo-devices.  The overall stream setup is
  7.  *    a bit different, however.  The server process gets back a
  8.  *    "naming" stream when it opens a remote link with the FS_PFS_MASTER
  9.  *    flag.  The kernel forwards naming operations (Fs_Open, Fs_Remove,
  10.  *    Fs_MakeDir, Fs_RemoveDir, Fs_MakeDevice, Fs_Rename, Fs_Hardlink)
  11.  *    to the server using the request response protocol over the
  12.  *    naming stream.  Thus the naming stream is like the server stream
  13.  *    returned to pseudo-device servers via its control stream, and the
  14.  *    client side of the naming stream is hung off the prefix table.
  15.  *
  16.  *    The pseudo-filesystem server can either return a pseudo-device
  17.  *    kind of connection in response to opens by clients, or it can
  18.  *    return a stream to a regular file or device.  Also, the server
  19.  *    can be private to a host, or it can export itself to the network.
  20.  *    
  21.  *
  22.  * Copyright 1987, 1988 Regents of the University of California
  23.  * Permission to use, copy, modify, and distribute this
  24.  * software and its documentation for any purpose and without
  25.  * fee is hereby granted, provided that the above copyright
  26.  * notice appear in all copies.  The University of California
  27.  * makes no representations about the suitability of this
  28.  * software for any purpose.  It is provided "as is" without
  29.  * express or implied warranty.
  30.  */
  31.  
  32. #ifndef lint
  33. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/fspdev/fspdevPfs.c,v 9.4 92/08/10 17:29:58 mgbaker Exp $ SPRITE (Berkeley)";
  34. #endif not lint
  35.  
  36. #include <sprite.h>
  37. #include <fs.h>
  38. #include <fsutil.h>
  39. #include <fsNameOps.h>
  40. #include <fsio.h>
  41. #include <fsconsist.h>
  42. #include <fsdm.h>
  43. #include <fsioLock.h>
  44. #include <fsprefix.h>
  45. #include <fsStat.h>
  46. #include <proc.h>
  47. #include <rpc.h>
  48. #include <fspdev.h>
  49. #include <fspdevInt.h>
  50. #include <dev/pfs.h>
  51. #include <string.h>
  52. #include <fsrecov.h>
  53. #include <recov.h>
  54.  
  55. static Fspdev_ServerIOHandle *PfsGetUserLevelIDs _ARGS_((
  56.     Fspdev_ServerIOHandle *pdevHandlePtr, Fs_FileID *prefixIDPtr, 
  57.     Fs_FileID *rootIDPtr));
  58.  
  59. /*
  60.  *----------------------------------------------------------------------------
  61.  *
  62.  * FspdevRmtLinkNameOpen --
  63.  *
  64.  *    The user-level server for a pseudo-filesystem is established by
  65.  *    opening a remote link type file with the FS_PFS_MASTER flag.
  66.  *    This procedure is invoked on the file server when remote links
  67.  *    are opened and detects this situation.  (If FS_PFS_MASTER is
  68.  *    not specified then Fsio_FileNameOpen is called and the remote link
  69.  *    is treated normally.)  Futhermore, there are two kinds of
  70.  *    pseudo-filesystem servers, "local agents" and "network agents".
  71.  *    If the FS_EXCLUSIVE flag is specified a local agent is created
  72.  *    and only the opening host sees the pseudo-filesystem.  Otherwise
  73.  *    the host sets up a network agent and exports the pseudo-filesystem
  74.  *    to the whole Sprite network.  In the latter case a control stream
  75.  *    is created here on the file server to record the server's existence.
  76.  *
  77.  * Results:
  78.  *    A status is returned that indicates conflict if another server exists.
  79.  *    A fileID and a streamID are also chosen for the naming stream.
  80.  *
  81.  * Side effects:
  82.  *    A control I/O handle is created here on the file server to record
  83.  *    who is the server for the pseudo device.  The handle for the
  84.  *    remote link file is unlocked.
  85.  *
  86.  *----------------------------------------------------------------------------
  87.  *
  88.  */
  89. ReturnStatus
  90. FspdevRmtLinkNameOpen(handlePtr, openArgsPtr, openResultsPtr)
  91.      register Fsio_FileIOHandle *handlePtr;    /* A handle from FslclLookup.
  92.                      * Should be LOCKED upon entry,
  93.                      * unlocked upon exit. */
  94.      Fs_OpenArgs        *openArgsPtr;    /* Standard open arguments */
  95.      Fs_OpenResults    *openResultsPtr;/* For returning ioFileID, streamID */
  96. {
  97.     register ReturnStatus status = SUCCESS;
  98.     register Fs_FileID *ioFileIDPtr = &openResultsPtr->ioFileID;
  99.     Fsrecov_HandleState    recovInfo;
  100.  
  101.     if ((openArgsPtr->useFlags & FS_PFS_MASTER) == 0) {
  102.     return(Fsio_FileNameOpen(handlePtr, openArgsPtr, openResultsPtr));
  103.     }
  104.     /*
  105.      * Generate an ID which is just like a FSIO_CONTROL_STREAM, except that
  106.      * the serverID will be set to us, the file server, for exported
  107.      * pseudo-filesystems, or set to the host running the server if the
  108.      * pseudo-filesystem is not exported.
  109.      */
  110.     ioFileIDPtr->type = FSIO_PFS_CONTROL_STREAM;
  111.     ioFileIDPtr->major = handlePtr->hdr.fileID.major;
  112.     ioFileIDPtr->minor = handlePtr->hdr.fileID.minor ^
  113.              (handlePtr->descPtr->version << 16);
  114.     if (openArgsPtr->useFlags & FS_EXCLUSIVE) {
  115.     /*
  116.      * The pseudo-filesystem server is private to the client host.
  117.      * We further uniqify its control handle ID to avoid conflict with
  118.      * files from other servers.  We set the serverID to the host
  119.      * running the server so we won't see closes or re-opens.
  120.      */
  121.     ioFileIDPtr->serverID = openArgsPtr->clientID;
  122.     ioFileIDPtr->major ^= rpc_SpriteID << 16;
  123.     Fsio_StreamCreateID(openArgsPtr->clientID, &openResultsPtr->streamID);
  124.     } else {
  125.     /*
  126.      * The pseudo-filesystem will be exported to the network.  Setting
  127.      * the serverID of the I/O handle to us means we'll see a close
  128.      * and possibly some reopens, we can do conflict checking.  However,
  129.      * the streamID we choose is used for the server half of the naming
  130.      * request-response stream, which sort of points sideways at the
  131.      * control handle on the client.  Thus there is no shadow stream,
  132.      * only a control handle here..
  133.      */
  134.     register Fspdev_ControlIOHandle *ctrlHandlePtr;
  135.  
  136.     ioFileIDPtr->serverID = rpc_SpriteID;
  137.     ctrlHandlePtr = FspdevControlHandleInit(ioFileIDPtr, handlePtr->hdr.name);
  138.     if (ctrlHandlePtr->serverID != NIL) {
  139.         status = FS_FILE_BUSY;
  140.     } else {
  141.         ctrlHandlePtr->serverID = openArgsPtr->clientID;
  142.         Fsio_StreamCreateID(openArgsPtr->clientID, &openResultsPtr->streamID);
  143.     }
  144.     /*
  145.      * We're the name server for this remote link, and if we're not
  146.      * the machine running the pseudo file system, then we update
  147.      * the recov box.
  148.      */
  149.     if (recov_Transparent && openArgsPtr->clientID != rpc_SpriteID) {
  150.         if (fsrecov_DebugLevel <= 2) {
  151.         printf("FspdevRmtLinkNameOpen: Adding pfs control handle ");
  152.         printf("%d.%d.%d.%d\n\tclient %d, serverID %d\n",
  153.             ((Fs_HandleHeader *) ctrlHandlePtr)->fileID.type,
  154.             ((Fs_HandleHeader *) ctrlHandlePtr)->fileID.serverID,
  155.             ((Fs_HandleHeader *) ctrlHandlePtr)->fileID.major,
  156.             ((Fs_HandleHeader *) ctrlHandlePtr)->fileID.minor,
  157.             openArgsPtr->clientID, ctrlHandlePtr->serverID);
  158.         }
  159. /* MIMIC PDEV_BUG */
  160.         if (Fsrecov_GetHandle(((Fs_HandleHeader *) ctrlHandlePtr)->fileID,
  161.             openArgsPtr->clientID, &recovInfo, FALSE) == SUCCESS) {
  162.         recovInfo.info = ctrlHandlePtr->serverID;
  163.         recovInfo.clientData = ctrlHandlePtr->seed;
  164.         if (Fsrecov_UpdateHandle(((Fs_HandleHeader *)
  165.             ctrlHandlePtr)->fileID, openArgsPtr->clientID,
  166.             &recovInfo) != SUCCESS) {
  167.             panic("FspdevRmtLinkNameOpen: couldn't update handle.");
  168.         }
  169.         } else {
  170. /* END_MIMIC_PDEV_BUG */
  171.         status = Fsrecov_AddHandle((Fs_HandleHeader *) ctrlHandlePtr,
  172.             (Fs_FileID *) NIL, openArgsPtr->clientID, 0,
  173.             ctrlHandlePtr->seed, TRUE);
  174.         /* We'll have to do better than this! */
  175.         if (status != SUCCESS) {
  176.             panic("FspdevRmtLinkNameOpen: couldn't add handle.");
  177.         }
  178.         }
  179.     }
  180.     Fsutil_HandleRelease(ctrlHandlePtr, TRUE);
  181.     }
  182.     openResultsPtr->streamData = (ClientData)NIL;
  183.     openResultsPtr->dataSize = 0;
  184.     Fsutil_HandleUnlock(handlePtr);
  185.     return(status);
  186. }
  187.  
  188. /*
  189.  *----------------------------------------------------------------------
  190.  *
  191.  * FspdevPfsIoOpen --
  192.  *
  193.  *    This is called from Fs_Open to complete setup of the stream
  194.  *    returned to the server of a pseudo-filesystem.  This stream
  195.  *    is called a "naming stream" because it will be used to
  196.  *    forward naming operations from the kernel up to the server.
  197.  *    It is structured just like the regular pseudo-device request
  198.  *    response stream, however.  The service end is returned to
  199.  *    the server and the client end is hung off the prefix table.
  200.  *
  201.  *    Note: we contrain the file name being opened to be the absolute
  202.  *    prefix of the pseudo-filesystem.  To fix this you'd need to extract
  203.  *    the prefix over at the file server and return it in the stream data.
  204.  * 
  205.  * Results:
  206.  *    SUCCESS, unless an exclusive (private) pseudo-filesystem server
  207.  *    already exists on this host.
  208.  *
  209.  * Side effects:
  210.  *    Three handles are created.  They have the same server, major, and minor,
  211.  *    but differ in their types (FSIO_PFS_CONTROL_STREAM, FSIO_SERVER_STREAM,
  212.  *    and FSIO_LCL_PSEUDO_STREAM).  The server stream is returned to our caller,
  213.  *    the client stream is hooked to the prefix table, and the control
  214.  *    stream is left around for conflict checking.
  215.  *
  216.  *----------------------------------------------------------------------
  217.  */
  218. /*ARGSUSED*/
  219. ReturnStatus
  220. FspdevPfsIoOpen(ioFileIDPtr, flagsPtr, clientID, streamData, name,
  221.     ioHandlePtrPtr)
  222.     register Fs_FileID    *ioFileIDPtr;    /* I/O fileID */
  223.     int            *flagsPtr;    /* FS_READ | FS_WRITE ... */
  224.     int            clientID;    /* Host doing the open */
  225.     ClientData        streamData;    /* Pointer to Fspdev_State. */
  226.     char        *name;        /* File name for error msgs */
  227.     Fs_HandleHeader    **ioHandlePtrPtr;/* Return - a locked handle set up for
  228.                      * I/O to a pseudo device, or NIL */
  229. {
  230.     register ReturnStatus    status = SUCCESS;
  231.     register Fspdev_ControlIOHandle *ctrlHandlePtr;
  232.     register Fspdev_ServerIOHandle *pdevHandlePtr;
  233.     register Fspdev_ClientIOHandle *cltHandlePtr;
  234.     Fs_HandleHeader        *prefixHdrPtr;
  235.     Fs_FileID            rootID;
  236.     int                domain;
  237.     int                id;
  238.     char            *ignoredName;
  239.     Fsprefix            *prefixPtr;
  240.     int                prefixFlags;
  241.  
  242.     /*
  243.      * Constrain the name to be an absolute prefix to keep things simple.
  244.      * Then verify that the prefix is not already handled by someone.
  245.      */
  246.     if (name[0] != '/') {
  247.     printf(
  248.         "Need absolute name (not \"%s\") for pseudo-filesystem\n", name);
  249.     return(FS_INVALID_ARG);
  250.     }
  251.     status = Fsprefix_Lookup(name,
  252.         FSPREFIX_IMPORTED|FSPREFIX_EXPORTED|FSPREFIX_EXACT, -1,
  253.         &prefixHdrPtr, &rootID, &ignoredName, &id, &domain, &prefixPtr);
  254.     if (status == SUCCESS) {
  255.     printf( "Prefix \"%s\" already serviced\n", name);
  256.     return(FS_FILE_BUSY);
  257.     } else {
  258.     status = SUCCESS;
  259.     }
  260.     /*
  261.      * Nuke this meaningless flag so we don't get an I/O control from Fs_Open.
  262.      */
  263.     *flagsPtr &= ~FS_TRUNC;
  264.     /*
  265.      * Create a control handle that contains the seed used to generate
  266.      * pseudo-device connections to the pseudo-filesystem server.  It is
  267.      * important to set the serverID so the control stream won't get scavenged.
  268.      */
  269.     ctrlHandlePtr = FspdevControlHandleInit(ioFileIDPtr, name);
  270.     ctrlHandlePtr->serverID = rpc_SpriteID;
  271.     /*
  272.      * Setup the request-response connection, and return the server
  273.      * end to the calling process.  We save a back pointer to the
  274.      * control stream so we can generate new request-response connections
  275.      * when clients do opens in the pseudo-filesystem, and so we
  276.      * can close it and clean up the prefix table when the server process exits.
  277.      */
  278.     ioFileIDPtr->type = FSIO_LCL_PSEUDO_STREAM;
  279.     ioFileIDPtr->serverID = rpc_SpriteID;
  280.     cltHandlePtr = FspdevConnect(ctrlHandlePtr, ioFileIDPtr, rpc_SpriteID, 1);
  281.     if (cltHandlePtr == (Fspdev_ClientIOHandle *)NIL) {
  282.     status = FAILURE;
  283.     goto cleanup;
  284.     }
  285.     pdevHandlePtr = cltHandlePtr->pdevHandlePtr;
  286.     *ioHandlePtrPtr = (Fs_HandleHeader *)pdevHandlePtr;
  287.     /*
  288.      * This ID gets passed in Fs_LookupArgs
  289.      * as the prefixID if the prefix is the root of the pseudo domain.
  290.      * It can be reset by the user with IOC_PFS_SET_ROOT.
  291.      */
  292.     pdevHandlePtr->userLevelID.type = 0;
  293.     pdevHandlePtr->userLevelID.serverID = 0;
  294.     pdevHandlePtr->userLevelID.major = 0;
  295.     pdevHandlePtr->userLevelID.minor = 0;
  296.     /*
  297.      * Install the client side of the connection in the prefix table.
  298.      */
  299.     prefixFlags = FSPREFIX_IMPORTED;
  300.     if (*flagsPtr & FS_EXCLUSIVE) {
  301.     prefixFlags |= FSPREFIX_LOCAL;
  302.     } else {
  303.     prefixFlags |= FSPREFIX_EXPORTED;
  304.     }
  305.     ctrlHandlePtr->prefixPtr = Fsprefix_Install(name,
  306.         (Fs_HandleHeader *)cltHandlePtr, FS_PSEUDO_DOMAIN, prefixFlags);
  307.     /*
  308.      * No migration of pseudo-filesystem servers.
  309.      */
  310.     Proc_NeverMigrate(Proc_GetCurrentProc());
  311.     Fsutil_HandleUnlock(cltHandlePtr);
  312. cleanup:
  313.     if (status != SUCCESS) {
  314.     Fsutil_HandleRelease(ctrlHandlePtr, TRUE);
  315.     *ioHandlePtrPtr = (Fs_HandleHeader *)NIL;
  316.     } else {
  317.     Fsutil_HandleUnlock(ctrlHandlePtr);
  318.     }
  319.     return(status);
  320.  
  321. }
  322.  
  323. /*
  324.  *----------------------------------------------------------------------------
  325.  *
  326.  * FspdevPfsExport --
  327.  *
  328.  *    This is called from the Fsrmt_RpcPrefix stub to complete setup for
  329.  *    a client that will be importing a prefix of a pseudo-filesystem
  330.  *    that has its server process on this host.  This has to add the
  331.  *    client to the client end of the naming request response stream
  332.  *    so future naming operations by that client are accepted here.
  333.  *    The remote Sprite host will call FspdevPfsNamingIoOpen to set
  334.  *    up the handle that it will attach to its own prefix table.
  335.  *
  336.  * Results:
  337.  *    This returns a fileID that the client will use to set up its I/O handle.
  338.  *
  339.  * Side effects:
  340.  *    A control I/O handle is created here on the file server to record
  341.  *    who is the server for the pseudo device.
  342.  *
  343.  *----------------------------------------------------------------------------
  344.  *
  345.  */
  346. ReturnStatus
  347. FspdevPfsExport(hdrPtr, clientID, ioFileIDPtr, dataSizePtr, clientDataPtr)
  348.      Fs_HandleHeader    *hdrPtr;    /* A handle from the prefix table. */
  349.      int        clientID;    /* Host ID of client importing prefix */
  350.      register Fs_FileID    *ioFileIDPtr;    /* Return - I/O handle ID */
  351.      int        *dataSizePtr;    /* Return - 0 */
  352.      ClientData        *clientDataPtr;    /* Return - NIL */
  353. {
  354.     register Fspdev_ClientIOHandle *cltHandlePtr = (Fspdev_ClientIOHandle *)hdrPtr;
  355.     register ReturnStatus status;
  356.  
  357.     Fsutil_HandleLock(cltHandlePtr);
  358.     if (FspdevPdevServerOK(cltHandlePtr->pdevHandlePtr)) {
  359.     (void)Fsconsist_IOClientOpen(&cltHandlePtr->clientList, clientID, 0, FALSE);
  360.     *ioFileIDPtr = cltHandlePtr->hdr.fileID;
  361.     ioFileIDPtr->type = FSIO_PFS_NAMING_STREAM;
  362.     *dataSizePtr = 0;
  363.     *clientDataPtr = (ClientData)NIL;
  364.     status = SUCCESS;
  365.     } else {
  366.     status = FAILURE;
  367.     }
  368.     Fsutil_HandleUnlock(cltHandlePtr);
  369.     return(status);
  370. }
  371.  
  372. /*
  373.  *----------------------------------------------------------------------
  374.  *
  375.  * FspdevPfsNamingIoOpen --
  376.  *
  377.  *    This is called from FsrmtImport to complete setup of the I/O
  378.  *    handle that hangs off the prefix table.  This stream
  379.  *    is called a "naming stream" because it will be used to
  380.  *    forward naming operations to the pseudo-filesystem server.  This
  381.  *    routine is similar to FspdevRmtPseudoStreamIoOpen, except that at
  382.  *    this point the server already knows about us, so we don't have
  383.  *    to contact it with Fsrmt_DeviceOpen.
  384.  *
  385.  * Results:
  386.  *    SUCCESS.
  387.  *
  388.  * Side effects:
  389.  *    Creates a FSIO_PFS_NAMING_STREAM, which is like a FSIO_RMT_PSEUDO_STREAM
  390.  *    in that its operations are forwarded via RPC to the host running
  391.  *    the pseudo-filesystem server.
  392.  *
  393.  *----------------------------------------------------------------------
  394.  */
  395. /*ARGSUSED*/
  396. ReturnStatus
  397. FspdevPfsNamingIoOpen(ioFileIDPtr, flagsPtr, clientID, streamData, name,
  398.     ioHandlePtrPtr)
  399.     register Fs_FileID    *ioFileIDPtr;    /* I/O fileID */
  400.     int            *flagsPtr;    /* FS_READ | FS_WRITE ... */
  401.     int            clientID;    /* Host doing the open */
  402.     ClientData        streamData;    /* Pointer to Fspdev_State. */
  403.     char        *name;        /* File name for error msgs */
  404.     Fs_HandleHeader    **ioHandlePtrPtr;/* Return - a locked handle set up for
  405.                      * I/O to a pseudo device, or NIL */
  406. {
  407.     Boolean found;
  408.     Fsrmt_IOHandle *rmtHandlePtr;
  409.  
  410.     found = Fsutil_HandleInstall(ioFileIDPtr, sizeof(Fsrmt_IOHandle), name,
  411.             FALSE, (Fs_HandleHeader **)&rmtHandlePtr);
  412.     if (!found) {
  413.     Fsutil_RecoveryInit(&rmtHandlePtr->recovery);
  414.     fs_Stats.object.remote++;
  415.     }
  416.     rmtHandlePtr->recovery.use.ref++;
  417.     *ioHandlePtrPtr = (Fs_HandleHeader *)rmtHandlePtr;
  418.     Fsutil_HandleUnlock(rmtHandlePtr);
  419.     return(SUCCESS);
  420. }
  421.  
  422. /*
  423.  *----------------------------------------------------------------------
  424.  *
  425.  * FspdevPfsDomainInfo --
  426.  *
  427.  *    Get information about a pseudo-file-system.
  428.  *
  429.  * Results:
  430.  *    An error status
  431.  *
  432.  * Side effects:
  433.  *    None.
  434.  *
  435.  *----------------------------------------------------------------------
  436.  */
  437.  
  438. ReturnStatus
  439. FspdevPfsDomainInfo(fileIDPtr, domainInfoPtr)
  440.     Fs_FileID *fileIDPtr;
  441.     Fs_DomainInfo *domainInfoPtr;
  442. {
  443.     ReturnStatus        status;
  444.     Pfs_Request            request;
  445.     Fs_RedirectInfo        *redirectPtr;
  446.     Fspdev_ClientIOHandle        *cltHandlePtr;
  447.     int                resultSize;
  448.  
  449.     status = FS_FILE_NOT_FOUND;
  450.     cltHandlePtr = Fsutil_HandleFetchType(Fspdev_ClientIOHandle, fileIDPtr);
  451.     if (cltHandlePtr != (Fspdev_ClientIOHandle *)NIL) {
  452.     Fsutil_HandleUnlock(cltHandlePtr);
  453.     /*
  454.      * Go to the pseudo-device server to get the domain information.
  455.      * We also change the fileID of the domain to be the user-visible
  456.      * one so that the getwd() library call works right.
  457.      */
  458.     *fileIDPtr = cltHandlePtr->pdevHandlePtr->userLevelID;
  459.     fileIDPtr->serverID = rpc_SpriteID;
  460.  
  461.     request.hdr.operation = PFS_DOMAIN_INFO;
  462.     request.param.domainInfo = *fileIDPtr;
  463.     resultSize = sizeof(Fs_DomainInfo);
  464.     status = FspdevPseudoStreamLookup(cltHandlePtr->pdevHandlePtr, &request,
  465.             0, (Address)NIL,
  466.             &resultSize, (Address)domainInfoPtr, &redirectPtr);
  467.     if (redirectPtr != (Fs_RedirectInfo *)NIL) {
  468.         free((Address)redirectPtr);
  469.     }
  470.     Fsutil_HandleRelease(cltHandlePtr, FALSE);
  471.     }
  472.     return(status);
  473. }
  474.  
  475.  
  476. /*
  477.  *----------------------------------------------------------------------
  478.  *
  479.  * FspdevPfsOpen --
  480.  *
  481.  *    Open a file served by a pseudo-filesystem server.  The stream returned
  482.  *    to the client can either be a pseudo-device connection to the
  483.  *    server of the pseudo-filesystem, or a regular stream that has
  484.  *    been passed off from the server process.
  485.  *
  486.  * Results:
  487.  *    SUCCESS, FS_REDIRECT, or some error code from the lookup on the server.
  488.  *    If FS_REDIRECT, then *newNameInfoPtr has prefix information.
  489.  *
  490.  * Side effects:
  491.  *    None here.  The connections are setup in the server IOControl routine.
  492.  *
  493.  *----------------------------------------------------------------------
  494.  */
  495.  
  496. ReturnStatus
  497. FspdevPfsOpen(prefixHandle, relativeName, argsPtr, resultsPtr, 
  498.          newNameInfoPtrPtr)
  499.     Fs_HandleHeader  *prefixHandle;    /* Handle from prefix table or cwd */
  500.     char       *relativeName;    /* The name of the file to open. */
  501.     Address       argsPtr;        /* Ref. to Fs_OpenArgs */
  502.     Address       resultsPtr;        /* Ref. to Fs_OpenResults */
  503.     Fs_RedirectInfo **newNameInfoPtrPtr;    /* We return this if the server leaves 
  504.                      * its domain during the lookup. */
  505. {
  506.     register Fspdev_ClientIOHandle    *cltHandlePtr;
  507.     register Fspdev_ServerIOHandle *pdevHandlePtr;
  508.     register Fs_OpenArgs        *openArgsPtr = (Fs_OpenArgs *)argsPtr;
  509.     Pfs_Request            request;
  510.     register ReturnStatus    status;
  511.     int                resultSize;
  512.  
  513.     cltHandlePtr = (Fspdev_ClientIOHandle *)prefixHandle;
  514.  
  515.     /*
  516.      * Set up the open arguments, and get ahold of the naming stream.
  517.      */
  518.     request.hdr.operation = PFS_OPEN;
  519.     pdevHandlePtr = PfsGetUserLevelIDs(cltHandlePtr->pdevHandlePtr,
  520.                 &openArgsPtr->prefixID, &openArgsPtr->rootID);
  521.     if (pdevHandlePtr == (Fspdev_ServerIOHandle *)NIL) {
  522.     return(FS_FILE_NOT_FOUND);
  523.     }
  524.     request.param.open = *openArgsPtr;
  525.  
  526.     resultSize = sizeof(Fs_OpenResults);
  527.  
  528.     /*
  529.      * Do the open.  The openResults are setup by the server-side IOC
  530.      * handler, so just we return.
  531.      */
  532.     status = FspdevPseudoStreamLookup(pdevHandlePtr, &request,
  533.         strlen(relativeName) + 1, (Address)relativeName,
  534.         &resultSize, resultsPtr, newNameInfoPtrPtr);
  535.     return(status);
  536. }
  537.  
  538. /*
  539.  *----------------------------------------------------------------------
  540.  *
  541.  * PfsGetUserLevelID --
  542.  *
  543.  *    This takes the lookup arguments for the pseudo-domain and maps them to
  544.  *    the correct request-response stream for naming, and to the user-level
  545.  *    versions of the prefix and root IDs.  Because of current directories,
  546.  *    the handle passed to the Pfs lookup routines won't always be the
  547.  *    top-level naming request-response stream.  However, we do get passed
  548.  *    the fileID of the root, from which we can fetch the right handle.
  549.  *
  550.  * Results:
  551.  *    Returns the pdevHandlePtr for the naming request-response stream.  This
  552.  *    is in turn passed to FspdevPseudoStreamLookup.  This also sets the prefixID
  553.  *    to be the user-level version.
  554.  *
  555.  * Side effects:
  556.  *    None.
  557.  *
  558.  *----------------------------------------------------------------------
  559.  */
  560.  
  561. static Fspdev_ServerIOHandle *
  562. PfsGetUserLevelIDs(pdevHandlePtr, prefixIDPtr, rootIDPtr)
  563.     Fspdev_ServerIOHandle *pdevHandlePtr;    /* Handle of name prefix */
  564.     Fs_FileID *prefixIDPtr;        /* Prefix fileID */
  565.     Fs_FileID *rootIDPtr;        /* ID of naming request-response */
  566. {
  567.     register Fspdev_ClientIOHandle *cltHandlePtr;
  568.  
  569.     *prefixIDPtr = pdevHandlePtr->userLevelID;
  570.     rootIDPtr->type = fsio_RmtToLclType[rootIDPtr->type];
  571.     cltHandlePtr = Fsutil_HandleFetchType(Fspdev_ClientIOHandle, rootIDPtr);
  572.     if (cltHandlePtr != (Fspdev_ClientIOHandle *)NIL) {
  573.     Fsutil_HandleRelease(cltHandlePtr, TRUE);
  574.     return(cltHandlePtr->pdevHandlePtr);
  575.     } else {
  576.     return((Fspdev_ServerIOHandle *)NIL);
  577.     }
  578. }
  579.  
  580. /*
  581.  *----------------------------------------------------------------------
  582.  *
  583.  * FspdevPfsOpenConnection --
  584.  *
  585.  *    This is called when the server does an IOC_PFS_OPEN to respond
  586.  *    to an open request issued by FspdevPfsOpen.  This sets up the server's
  587.  *    half of the pseudo-device connection, while FspdevPfsOpen completes
  588.  *    the connection by opening the client's half.  This knows it is
  589.  *    executing in the kernel context of the server process so it can
  590.  *    establish the user-level streamID needed by the server.
  591.  *
  592.  * Results:
  593.  *    A streamID that has to be returned to the server.
  594.  *
  595.  * Side effects:
  596.  *    Set up the state for a pseudo-device connection.
  597.  *
  598.  *----------------------------------------------------------------------
  599.  */
  600. int
  601. FspdevPfsOpenConnection(namingPdevHandlePtr, srvrFileIDPtr, openResultsPtr)
  602.     Fspdev_ServerIOHandle    *namingPdevHandlePtr;/* From naming request-response */
  603.     Fs_FileID *srvrFileIDPtr;        /* FileID from user-level server */
  604.     Fs_OpenResults *openResultsPtr;    /* Info returned to client's open */
  605. {
  606.     register Fspdev_ControlIOHandle *ctrlHandlePtr;
  607.     register Fspdev_ClientIOHandle *cltHandlePtr;
  608.     register Fs_Stream *srvStreamPtr;
  609.     register Fs_Stream *cltStreamPtr;
  610.     int newStreamID;
  611.     register Fs_FileID    *fileIDPtr;    /* FileID for new connection */
  612.  
  613.     /*
  614.      * Pick an I/O fileID for the connection.
  615.      */
  616.     ctrlHandlePtr = namingPdevHandlePtr->ctrlHandlePtr;
  617.     ctrlHandlePtr->seed++;
  618.     fileIDPtr = &openResultsPtr->ioFileID;
  619.     fileIDPtr->type = FSIO_LCL_PFS_STREAM;
  620.     fileIDPtr->serverID = rpc_SpriteID;
  621.     fileIDPtr->major = ctrlHandlePtr->rmt.hdr.fileID.major;
  622.     fileIDPtr->minor = (ctrlHandlePtr->rmt.hdr.fileID.minor << 12)
  623.             ^ ctrlHandlePtr->seed;
  624.  
  625.     cltHandlePtr = FspdevConnect(ctrlHandlePtr, fileIDPtr,
  626.             namingPdevHandlePtr->open.clientID, 0);
  627.     if (cltHandlePtr == (Fspdev_ClientIOHandle *)NIL) {
  628.     printf( "FspdevPfsOpenConnection failing\n");
  629.     return(-1);
  630.     }
  631.     /*
  632.      * Set the ioFileID type. (FspdevConnect has munged it to FSIO_SERVER_STREAM.)
  633.      * The open.clientID has been set curtesy of the PFS_OPEN RequestResponse.
  634.      */
  635.     if (namingPdevHandlePtr->open.clientID == rpc_SpriteID) {
  636.     fileIDPtr->type = FSIO_LCL_PFS_STREAM;
  637.     } else {
  638.     fileIDPtr->type = FSIO_RMT_PFS_STREAM;
  639.     }
  640.     /*
  641.      * Save the server process's ID for the connection.
  642.      */
  643.     cltHandlePtr->pdevHandlePtr->userLevelID = *srvrFileIDPtr;
  644.  
  645.     /*
  646.      * Set up a stream to the server's half of the connection and
  647.      * then choose a user level streamID.
  648.      */
  649.     srvStreamPtr = Fsio_StreamCreate(rpc_SpriteID, rpc_SpriteID,
  650.             (Fs_HandleHeader *)cltHandlePtr->pdevHandlePtr,
  651.             FS_READ|FS_USER, namingPdevHandlePtr->open.name);
  652.     if (Fs_GetStreamID(srvStreamPtr, &newStreamID) != SUCCESS) {
  653.     (void)Fsio_StreamClientClose(&srvStreamPtr->clientList, rpc_SpriteID);
  654.     Fsio_StreamDestroy(srvStreamPtr);
  655.     Sync_LockClear(&cltHandlePtr->pdevHandlePtr->lock);
  656.     Fsutil_HandleRemove(cltHandlePtr->pdevHandlePtr);
  657.     Fsutil_HandleRemove(cltHandlePtr);
  658.     fs_Stats.object.pseudoStreams--;
  659.     newStreamID = -1;
  660.     } else {
  661.     /*
  662.      * Set up a stream to the client's half of the connection.
  663.      */
  664.     cltStreamPtr = Fsio_StreamCreate(rpc_SpriteID,
  665.                 namingPdevHandlePtr->open.clientID,
  666.                 (Fs_HandleHeader *)cltHandlePtr,
  667.                 namingPdevHandlePtr->open.useFlags,
  668.                 namingPdevHandlePtr->open.name);
  669.     openResultsPtr->nameID = openResultsPtr->ioFileID;
  670.     openResultsPtr->streamID = cltStreamPtr->hdr.fileID;
  671.     openResultsPtr->dataSize = 0;
  672.     openResultsPtr->streamData = (ClientData)NIL;
  673.     Fsutil_HandleRelease(cltStreamPtr, TRUE);
  674.     Fsutil_HandleUnlock(cltHandlePtr);
  675.     Fsutil_HandleUnlock(srvStreamPtr);
  676.     }
  677.     return(newStreamID);
  678. }
  679.  
  680. /*
  681.  *----------------------------------------------------------------------
  682.  *
  683.  * FspdevPfsStreamIoOpen --
  684.  *
  685.  *    This is called from Fs_Open to complete setup of a client's
  686.  *    stream to a pseudo-filesystem server.  The server is running on this
  687.  *    host, and the pseudo-device connection has already been established.
  688.  *    This routine just latches onto it and returns.
  689.  * 
  690.  * Results:
  691.  *    SUCCESS, unless the server process has died recently.
  692.  *
  693.  * Side effects:
  694.  *    Fetches the handle, which increments its ref count.  The
  695.  *    handle is unlocked before returning.
  696.  *
  697.  *----------------------------------------------------------------------
  698.  */
  699. /*ARGSUSED*/
  700. ReturnStatus
  701. FspdevPfsStreamIoOpen(ioFileIDPtr, flagsPtr, clientID, streamData, name,
  702.     ioHandlePtrPtr)
  703.     register Fs_FileID    *ioFileIDPtr;    /* I/O fileID */
  704.     int            *flagsPtr;    /* FS_READ | FS_WRITE ... */
  705.     int            clientID;    /* Host doing the open */
  706.     ClientData        streamData;    /* Pointer to Fspdev_State. */
  707.     char        *name;        /* File name for error msgs */
  708.     Fs_HandleHeader    **ioHandlePtrPtr;/* Return - a locked handle set up for
  709.                      * I/O to a pseudo device, or NIL */
  710. {
  711.     register Fspdev_ClientIOHandle *cltHandlePtr;
  712.  
  713.     cltHandlePtr = Fsutil_HandleFetchType(Fspdev_ClientIOHandle, ioFileIDPtr);
  714.     if (cltHandlePtr == (Fspdev_ClientIOHandle *)NIL) {
  715.     printf( "FspdevPfsStreamIoOpen, no handle\n");
  716.     *ioHandlePtrPtr = (Fs_HandleHeader *)NIL;
  717.     return(FS_FILE_NOT_FOUND);
  718.     } else {
  719.     if (cltHandlePtr->hdr.name != (char *)NIL) {
  720.         free((Address)cltHandlePtr->hdr.name);
  721.     }
  722.     cltHandlePtr->hdr.name = (char *)malloc(strlen(name) + 1);
  723.     (void)strcpy(cltHandlePtr->hdr.name, name);
  724.     *ioHandlePtrPtr = (Fs_HandleHeader *)cltHandlePtr;
  725.     if (*flagsPtr & FS_EXECUTE) {         /* Promote execute access to */
  726.         *flagsPtr |= FS_READ;          /* read access. JMS */
  727.     }
  728.     Fsutil_HandleUnlock(cltHandlePtr);
  729.     return(SUCCESS);
  730.     }
  731. }
  732.  
  733. /*
  734.  *----------------------------------------------------------------------
  735.  *
  736.  * FspdevRmtPfsStreamIoOpen --
  737.  *
  738.  *    This is called from Fs_Open to complete setup of a client's
  739.  *    stream to a remote pseudo-filesystem server.  The server is running
  740.  *    on this    host, and the pseudo-device connection has already been
  741.  *    established.  This routine just sets up a remote handle that
  742.  *    references the connection.
  743.  * 
  744.  * Results:
  745.  *    SUCCESS.
  746.  *
  747.  * Side effects:
  748.  *    Installs a remote I/O handle.
  749.  *
  750.  *----------------------------------------------------------------------
  751.  */
  752. /*ARGSUSED*/
  753. ReturnStatus
  754. FspdevRmtPfsStreamIoOpen(ioFileIDPtr, flagsPtr, clientID, streamData, name,
  755.     ioHandlePtrPtr)
  756.     register Fs_FileID    *ioFileIDPtr;    /* I/O fileID */
  757.     int            *flagsPtr;    /* FS_READ | FS_WRITE ... */
  758.     int            clientID;    /* Host doing the open */
  759.     ClientData        streamData;    /* NIL. */
  760.     char        *name;        /* File name for error msgs */
  761.     Fs_HandleHeader    **ioHandlePtrPtr;/* Return - FSIO_RMT_PFS_STREAM handle */
  762. {
  763.     Fsrmt_IOHandleInit(ioFileIDPtr, *flagsPtr, name, ioHandlePtrPtr);
  764.     if (*flagsPtr & FS_EXECUTE) {         /* Promote execute access to */
  765.     *flagsPtr |= FS_READ;             /* read access. JMS */
  766.     }
  767.     return(SUCCESS);
  768. }
  769.  
  770. /*
  771.  *----------------------------------------------------------------------
  772.  *
  773.  * FspdevPfsGetAttrPath --
  774.  *
  775.  *    Get the attributes of a file in a pseudo-filesystem.
  776.  *
  777.  * Results:
  778.  *    A return code from the RPC or the remote server.
  779.  *
  780.  * Side effects:
  781.  *    None.
  782.  *
  783.  *----------------------------------------------------------------------
  784.  */
  785. ReturnStatus
  786. FspdevPfsGetAttrPath(prefixHandle, relativeName, argsPtr, resultsPtr,
  787.                  newNameInfoPtrPtr)
  788.     Fs_HandleHeader *prefixHandle;    /* Handle from the prefix table */
  789.     char           *relativeName;    /* The name of the file. */
  790.     Address        argsPtr;        /* Bundled arguments for us */
  791.     Address        resultsPtr;        /* Where to store attributes */
  792.     Fs_RedirectInfo **newNameInfoPtrPtr;    /* We return this if the server leaves 
  793.                      * its domain during the lookup. */
  794. {
  795.     register Fspdev_ServerIOHandle    *pdevHandlePtr;
  796.     Pfs_Request            request;
  797.     register ReturnStatus    status;
  798.     register Fs_OpenArgs        *openArgsPtr;
  799.     register Fs_GetAttrResults    *getAttrResultsPtr;
  800.     int                resultSize;
  801.  
  802.     pdevHandlePtr = ((Fspdev_ClientIOHandle *)prefixHandle)->pdevHandlePtr;
  803.     openArgsPtr = (Fs_OpenArgs *)argsPtr;
  804.  
  805.     request.hdr.operation = PFS_GET_ATTR;
  806.     pdevHandlePtr = PfsGetUserLevelIDs(pdevHandlePtr,
  807.                 &openArgsPtr->prefixID, &openArgsPtr->rootID);
  808.     if (pdevHandlePtr == (Fspdev_ServerIOHandle *)NIL) {
  809.     return(FS_FILE_NOT_FOUND);
  810.     }
  811.     request.param.open = *(Fs_OpenArgs *)argsPtr;
  812.  
  813.     getAttrResultsPtr = (Fs_GetAttrResults *)resultsPtr;
  814.     resultSize = sizeof(Fs_Attributes);
  815.  
  816.     status = FspdevPseudoStreamLookup(pdevHandlePtr, &request,
  817.         strlen(relativeName) + 1, (Address)relativeName,
  818.         &resultSize, (Address)getAttrResultsPtr->attrPtr,
  819.         newNameInfoPtrPtr);
  820.     /*
  821.      * Patch the serverID in the attributes so it matches the serverID
  822.      * given in the prefix table.  This is needed to make getwd() work.
  823.      */
  824.     getAttrResultsPtr->attrPtr->serverID = rpc_SpriteID;
  825.     /*
  826.      * The pseudo-filesystem server has given us all the attributes.  There
  827.      * is no reason to do a getIOAttr so we inhibit that with a special
  828.      * ioFileID type.  However, because Fsutil_DomainInfo calls this routine
  829.      * to fill in the file ID for the user-visible prefix table entry
  830.      * we set up the rest of the fields to match the return of a stat() call.
  831.      */
  832.     getAttrResultsPtr->fileIDPtr->type = -1;
  833.     getAttrResultsPtr->fileIDPtr->serverID = getAttrResultsPtr->attrPtr->serverID;
  834.     getAttrResultsPtr->fileIDPtr->major = getAttrResultsPtr->attrPtr->domain;
  835.     getAttrResultsPtr->fileIDPtr->minor = getAttrResultsPtr->attrPtr->fileNumber;
  836.     return(status);
  837. }
  838.  
  839. /*
  840.  *----------------------------------------------------------------------
  841.  *
  842.  * FspdevPfsSetAttrPath --
  843.  *
  844.  *    Set the attributes of a file in a pseudo-filesystem.
  845.  *
  846.  * Results:
  847.  *    A return code from the RPC or the remote server.
  848.  *
  849.  * Side effects:
  850.  *    Setting those attributes.
  851.  *
  852.  *----------------------------------------------------------------------
  853.  */
  854. ReturnStatus
  855. FspdevPfsSetAttrPath(prefixHandle, relativeName, argsPtr, resultsPtr,
  856.                  newNameInfoPtrPtr)
  857.     Fs_HandleHeader *prefixHandle;    /* Handle from the prefix table */
  858.     char           *relativeName;    /* The name of the file. */
  859.     Address        argsPtr;        /* Bundled arguments for us */
  860.     Address        resultsPtr;        /* Where to store attributes */
  861.     Fs_RedirectInfo **newNameInfoPtrPtr;    /* We return this if the server leaves 
  862.                      * its domain during the lookup. */
  863. {
  864.     register Fspdev_ServerIOHandle    *pdevHandlePtr;
  865.     Pfs_Request            request;
  866.     register ReturnStatus    status;
  867.     register Fs_SetAttrArgs    *setAttrArgsPtr;
  868.     register Pfs_SetAttrData    *setAttrDataPtr;
  869.     register int        nameLength;
  870.     register int        dataLength;
  871.     int                zero = 0;
  872.  
  873.     pdevHandlePtr = ((Fspdev_ClientIOHandle *)prefixHandle)->pdevHandlePtr;
  874.  
  875.     setAttrArgsPtr = (Fs_SetAttrArgs *)argsPtr;
  876.  
  877.     request.hdr.operation = PFS_SET_ATTR;
  878.     pdevHandlePtr = PfsGetUserLevelIDs(pdevHandlePtr,
  879.                 &setAttrArgsPtr->openArgs.prefixID,
  880.                 &setAttrArgsPtr->openArgs.rootID);
  881.     if (pdevHandlePtr == (Fspdev_ServerIOHandle *)NIL) {
  882.     return(FS_FILE_NOT_FOUND);
  883.     }
  884.     request.param.open = setAttrArgsPtr->openArgs;
  885.  
  886.     /*
  887.      * The dataLength includes 4 bytes of name inside the Pfs_SetAttrData
  888.      * so there is room for the trailing null byte.
  889.      */
  890.     nameLength = strlen(relativeName);
  891.     dataLength = sizeof(Pfs_SetAttrData) + nameLength;
  892.  
  893.     setAttrDataPtr = (Pfs_SetAttrData *)malloc(dataLength);
  894.     setAttrDataPtr->attr = setAttrArgsPtr->attr;
  895.     setAttrDataPtr->flags = setAttrArgsPtr->flags;
  896.     setAttrDataPtr->nameLength = nameLength;
  897.     (void)strcpy(setAttrDataPtr->name, relativeName);
  898.  
  899.     status = FspdevPseudoStreamLookup(pdevHandlePtr, &request,
  900.         dataLength, (Address)setAttrDataPtr,
  901.         &zero, (Address)NIL, newNameInfoPtrPtr);
  902.     free((Address)setAttrDataPtr);
  903.     /*
  904.      * The pseudo-filesystem server has dealt with all the attributes so
  905.      * we don't fill in the ioFileID.
  906.      */
  907.     ((Fs_FileID *)resultsPtr)->type = -1;
  908.     return(status);
  909. }
  910.  
  911. /*
  912.  *----------------------------------------------------------------------
  913.  *
  914.  * FspdevPfsMakeDir --
  915.  *
  916.  *    Make the named directory in a pseudo-filesystem.
  917.  *
  918.  * Results:
  919.  *    A return code from the file server or the RPC.
  920.  *
  921.  * Side effects:
  922.  *    Makes the directory.
  923.  *
  924.  *----------------------------------------------------------------------
  925.  */
  926. /*ARGSUSED*/
  927. ReturnStatus
  928. FspdevPfsMakeDir(prefixHandle, relativeName, argsPtr, resultsPtr, 
  929.         newNameInfoPtrPtr)
  930.     Fs_HandleHeader *prefixHandle;   /* Handle from the prefix table */
  931.     char        *relativeName;   /* The name of the directory to create */
  932.     Address        argsPtr;        /* Ref. to Fs_OpenArgs */
  933.     Address        resultsPtr;        /* == NIL */
  934.     Fs_RedirectInfo **newNameInfoPtrPtr;/* We return this if the server leaves 
  935.                     * its domain during the lookup. */
  936. {
  937.     register Fspdev_ServerIOHandle    *pdevHandlePtr;
  938.     register Fs_OpenArgs        *openArgsPtr;
  939.     Pfs_Request            request;
  940.     register ReturnStatus    status;
  941.     int                resultSize;
  942.  
  943.     pdevHandlePtr = ((Fspdev_ClientIOHandle *)prefixHandle)->pdevHandlePtr;
  944.     openArgsPtr = (Fs_OpenArgs *)argsPtr;
  945.  
  946.     request.hdr.operation = PFS_MAKE_DIR;
  947.     pdevHandlePtr = PfsGetUserLevelIDs(pdevHandlePtr,
  948.                 &openArgsPtr->prefixID, &openArgsPtr->rootID);
  949.     if (pdevHandlePtr == (Fspdev_ServerIOHandle *)NIL) {
  950.     return(FS_FILE_NOT_FOUND);
  951.     }
  952.     request.param.makeDir = *openArgsPtr;
  953.  
  954.     resultSize = 0;
  955.  
  956.     status = FspdevPseudoStreamLookup(pdevHandlePtr, &request,
  957.         strlen(relativeName) + 1, (Address)relativeName,
  958.         &resultSize, resultsPtr, newNameInfoPtrPtr);
  959.     return(status);
  960. }
  961.  
  962. /*
  963.  *----------------------------------------------------------------------
  964.  *
  965.  * FspdevPfsMakeDevice --
  966.  *
  967.  *    Create a device file in a pseudo-filesystem.
  968.  *
  969.  * Results:
  970.  *    None.
  971.  *
  972.  * Side effects:
  973.  *    Makes a device file.
  974.  *
  975.  *----------------------------------------------------------------------
  976.  */
  977. /*ARGSUSED*/
  978. ReturnStatus
  979. FspdevPfsMakeDevice(prefixHandle, relativeName, argsPtr, resultsPtr,
  980.                    newNameInfoPtrPtr)
  981.     Fs_HandleHeader *prefixHandle;   /* Handle from the prefix table */
  982.     char           *relativeName;   /* The name of the file. */
  983.     Address        argsPtr;        /* Ref. to FsMakeDevArgs */
  984.     Address        resultsPtr;        /* == NIL */
  985.     Fs_RedirectInfo **newNameInfoPtrPtr;/* We return this if the server leaves 
  986.                     * its domain during the lookup. */
  987. {
  988.     register Fspdev_ServerIOHandle    *pdevHandlePtr;
  989.     register Fs_MakeDeviceArgs    *makeDevArgsPtr;
  990.     Pfs_Request            request;
  991.     register ReturnStatus    status;
  992.     int                resultSize;
  993.  
  994.     pdevHandlePtr = ((Fspdev_ClientIOHandle *)prefixHandle)->pdevHandlePtr;
  995.     makeDevArgsPtr = (Fs_MakeDeviceArgs *)argsPtr;
  996.  
  997.     request.hdr.operation = PFS_MAKE_DEVICE;
  998.     pdevHandlePtr = PfsGetUserLevelIDs(pdevHandlePtr,
  999.         &makeDevArgsPtr->open.prefixID, &makeDevArgsPtr->open.rootID);
  1000.     if (pdevHandlePtr == (Fspdev_ServerIOHandle *)NIL) {
  1001.     return(FS_FILE_NOT_FOUND);
  1002.     }
  1003.     request.param.makeDevice = *makeDevArgsPtr;
  1004.  
  1005.     resultSize = 0;
  1006.  
  1007.     status = FspdevPseudoStreamLookup(pdevHandlePtr, &request,
  1008.         strlen(relativeName) + 1, (Address)relativeName,
  1009.         &resultSize, resultsPtr, newNameInfoPtrPtr);
  1010.     return(status);
  1011. }
  1012.  
  1013. /*
  1014.  *----------------------------------------------------------------------
  1015.  *
  1016.  * FspdevPfsRemove --
  1017.  *
  1018.  *    Remove a file served by a pseudo-filesystem server.
  1019.  *
  1020.  * Results:
  1021.  *    None.
  1022.  *
  1023.  * Side effects:
  1024.  *    Does the remove.
  1025.  *
  1026.  *----------------------------------------------------------------------
  1027.  */
  1028. /*ARGSUSED*/
  1029. ReturnStatus
  1030. FspdevPfsRemove(prefixHandle, relativeName, argsPtr, resultsPtr, 
  1031.            newNameInfoPtrPtr)
  1032.     Fs_HandleHeader   *prefixHandle;    /* Handle from the prefix table */
  1033.     char        *relativeName;    /* The name of the file to remove */
  1034.     Address        argsPtr;        /* Ref to Fs_LookupArgs */
  1035.     Address        resultsPtr;        /* == NIL */
  1036.     Fs_RedirectInfo **newNameInfoPtrPtr; /* We return this if the server leaves 
  1037.                        its domain during the lookup. */
  1038. {
  1039.     register Fspdev_ServerIOHandle    *pdevHandlePtr;
  1040.     register Fs_LookupArgs    *lookupArgsPtr;
  1041.     Pfs_Request            request;
  1042.     register ReturnStatus    status;
  1043.     int                resultSize;
  1044.  
  1045.     pdevHandlePtr = ((Fspdev_ClientIOHandle *)prefixHandle)->pdevHandlePtr;
  1046.     lookupArgsPtr = (Fs_LookupArgs *)argsPtr;
  1047.  
  1048.     request.hdr.operation = PFS_REMOVE;
  1049.     pdevHandlePtr = PfsGetUserLevelIDs(pdevHandlePtr,
  1050.                 &lookupArgsPtr->prefixID, &lookupArgsPtr->rootID);
  1051.     if (pdevHandlePtr == (Fspdev_ServerIOHandle *)NIL) {
  1052.     return(FS_FILE_NOT_FOUND);
  1053.     }
  1054.     request.param.remove = *lookupArgsPtr;
  1055.  
  1056.     resultSize = 0;
  1057.  
  1058.     status = FspdevPseudoStreamLookup(pdevHandlePtr, &request,
  1059.         strlen(relativeName) + 1, (Address)relativeName,
  1060.         &resultSize, resultsPtr, newNameInfoPtrPtr);
  1061.     return(status);
  1062. }
  1063.  
  1064. /*
  1065.  *----------------------------------------------------------------------
  1066.  *
  1067.  * FspdevPfsRemoveDir --
  1068.  *
  1069.  *    Remove a directory in a pseudo-filesystem.
  1070.  *
  1071.  * Results:
  1072.  *    None.
  1073.  *
  1074.  * Side effects:
  1075.  *    Does the remove.
  1076.  *
  1077.  *----------------------------------------------------------------------
  1078.  */
  1079. /*ARGSUSED*/
  1080. ReturnStatus
  1081. FspdevPfsRemoveDir(prefixHandle, relativeName, argsPtr, resultsPtr, 
  1082.            newNameInfoPtrPtr)
  1083.     Fs_HandleHeader   *prefixHandle;    /* Handle from the prefix table */
  1084.     char        *relativeName;    /* The name of the file to remove */
  1085.     Address        argsPtr;        /* Ref to Fs_LookupArgs */
  1086.     Address        resultsPtr;        /* == NIL */
  1087.     Fs_RedirectInfo **newNameInfoPtrPtr; /* We return this if the server leaves 
  1088.                        its domain during the lookup. */
  1089. {
  1090.     register Fspdev_ServerIOHandle    *pdevHandlePtr;
  1091.     register Fs_LookupArgs    *lookupArgsPtr;
  1092.     Pfs_Request            request;
  1093.     register ReturnStatus    status;
  1094.     int                resultSize;
  1095.  
  1096.     pdevHandlePtr = ((Fspdev_ClientIOHandle *)prefixHandle)->pdevHandlePtr;
  1097.     lookupArgsPtr = (Fs_LookupArgs *)argsPtr;
  1098.  
  1099.     request.hdr.operation = PFS_REMOVE_DIR;
  1100.     pdevHandlePtr = PfsGetUserLevelIDs(pdevHandlePtr,
  1101.                 &lookupArgsPtr->prefixID, &lookupArgsPtr->rootID);
  1102.     if (pdevHandlePtr == (Fspdev_ServerIOHandle *)NIL) {
  1103.     return(FS_FILE_NOT_FOUND);
  1104.     }
  1105.     request.param.removeDir = *lookupArgsPtr;
  1106.  
  1107.     resultSize = 0;
  1108.  
  1109.     status = FspdevPseudoStreamLookup(pdevHandlePtr, &request,
  1110.         strlen(relativeName) + 1, (Address)relativeName,
  1111.         &resultSize, resultsPtr, newNameInfoPtrPtr);
  1112.     return(status);
  1113. }
  1114.  
  1115. /*
  1116.  *----------------------------------------------------------------------
  1117.  *
  1118.  * FspdevPfsRename --
  1119.  *
  1120.  *    Rename a file is a pseudo-filesystem.
  1121.  *
  1122.  * Results:
  1123.  *    A return status.
  1124.  *
  1125.  * Side effects:
  1126.  *    None.
  1127.  *
  1128.  *----------------------------------------------------------------------
  1129.  */
  1130. ReturnStatus
  1131. FspdevPfsRename(prefixHandle1, relativeName1, prefixHandle2, relativeName2,
  1132.     lookupArgsPtr, newNameInfoPtrPtr, name1ErrorPtr)
  1133.     Fs_HandleHeader *prefixHandle1;    /* Handle from the prefix table */
  1134.     char *relativeName1;        /* The new name of the file. */
  1135.     Fs_HandleHeader *prefixHandle2;    /* Token from the prefix table */
  1136.     char *relativeName2;        /* The new name of the file. */
  1137.     Fs_LookupArgs *lookupArgsPtr;    /* Contains IDs */
  1138.     Fs_RedirectInfo **newNameInfoPtrPtr;    /* We return this if the server leaves 
  1139.                      * its domain during the lookup. */
  1140.     Boolean *name1ErrorPtr;    /* TRUE if redirect info or other error
  1141.                  * condition if for the first pathname,
  1142.                  * FALSE means error is on second pathname. */
  1143. {
  1144.     return(FspdevPfs2Path(PFS_RENAME, prefixHandle1, relativeName1, prefixHandle2,
  1145.         relativeName2, lookupArgsPtr, newNameInfoPtrPtr, name1ErrorPtr));
  1146. }
  1147.  
  1148. /*
  1149.  *----------------------------------------------------------------------
  1150.  *
  1151.  * FspdevPfsHardLink --
  1152.  *
  1153.  *    Make a hard link between two files in a pseudo-filesystem.
  1154.  *
  1155.  * Results:
  1156.  *    A return status.
  1157.  *
  1158.  * Side effects:
  1159.  *    None.
  1160.  *
  1161.  *----------------------------------------------------------------------
  1162.  */
  1163. /*ARGSUSED*/
  1164. ReturnStatus
  1165. FspdevPfsHardLink(prefixHandle1, relativeName1, prefixHandle2, relativeName2,
  1166.         lookupArgsPtr, newNameInfoPtrPtr, name1ErrorPtr)
  1167.     Fs_HandleHeader *prefixHandle1;    /* Token from the prefix table */
  1168.     char *relativeName1;        /* The new name of the file. */
  1169.     Fs_HandleHeader *prefixHandle2;    /* Token from the prefix table */
  1170.     char *relativeName2;        /* The new name of the file. */
  1171.     Fs_LookupArgs *lookupArgsPtr;    /* Contains IDs */
  1172.     Fs_RedirectInfo **newNameInfoPtrPtr;    /* We return this if the server 
  1173.                      * leaves its domain during the lookup*/
  1174.     Boolean *name1ErrorPtr;    /* TRUE if redirect info or other error is
  1175.                  * for first path, FALSE if for the second. */
  1176. {
  1177.     return(FspdevPfs2Path(PFS_HARD_LINK, prefixHandle1, relativeName1,prefixHandle2,
  1178.         relativeName2, lookupArgsPtr, newNameInfoPtrPtr, name1ErrorPtr));
  1179. }
  1180.  
  1181. /*
  1182.  *----------------------------------------------------------------------
  1183.  *
  1184.  * FspdevPfs2Path --
  1185.  *
  1186.  *    Rename or Hardlink a file is a pseudo-filesystem.  This bundles the
  1187.  *    arguments up for shipment to the server.  The prefix fileIDs are
  1188.  *    mapped to the server's version of them.
  1189.  *
  1190.  * Results:
  1191.  *    A return status.
  1192.  *
  1193.  * Side effects:
  1194.  *    Either a rename or a link.
  1195.  *
  1196.  *----------------------------------------------------------------------
  1197.  */
  1198. ReturnStatus
  1199. FspdevPfs2Path(operation,prefixHandle1, relativeName1, prefixHandle2, relativeName2,
  1200.     lookupArgsPtr, newNameInfoPtrPtr, name1ErrorPtr)
  1201.     Pdev_Op operation;            /* PFS_RENAME or PFS_HARD_LINK */
  1202.     Fs_HandleHeader *prefixHandle1;    /* Handle from the prefix table */
  1203.     char *relativeName1;        /* The new name of the file. */
  1204.     Fs_HandleHeader *prefixHandle2;    /* Token from the prefix table */
  1205.     char *relativeName2;        /* The new name of the file. */
  1206.     Fs_LookupArgs *lookupArgsPtr;    /* Contains IDs */
  1207.     Fs_RedirectInfo **newNameInfoPtrPtr;    /* We return this if the server leaves 
  1208.                      * its domain during the lookup. */
  1209.     Boolean *name1ErrorPtr;    /* TRUE if redirect info or other error
  1210.                  * condition if for the first pathname,
  1211.                  * FALSE means error is on second pathname. */
  1212. {
  1213.     register Fspdev_ServerIOHandle    *pdevHandlePtr;
  1214.     register Fspdev_ServerIOHandle    *pdevHandle2Ptr;
  1215.     Fs_2PathData            *dataPtr;
  1216.     Pfs_Request            request;
  1217.     register ReturnStatus    status;
  1218.  
  1219.     pdevHandlePtr = ((Fspdev_ClientIOHandle *)prefixHandle1)->pdevHandlePtr;
  1220.  
  1221.     request.hdr.operation = operation;
  1222.     pdevHandlePtr = PfsGetUserLevelIDs(pdevHandlePtr,
  1223.                 &lookupArgsPtr->prefixID, &lookupArgsPtr->rootID);
  1224.     if (pdevHandlePtr == (Fspdev_ServerIOHandle *)NIL) {
  1225.     return(FS_FILE_NOT_FOUND);
  1226.     }
  1227.     request.param.rename.lookup = *lookupArgsPtr;
  1228.     if ((prefixHandle2 == (Fs_HandleHeader *)NIL) ||
  1229.     (prefixHandle2->fileID.type != prefixHandle1->fileID.type) ||
  1230.     (prefixHandle2->fileID.major != prefixHandle1->fileID.major) ||
  1231.     (prefixHandle2->fileID.minor != prefixHandle1->fileID.minor)) {
  1232.     /*
  1233.      * Second prefix isn't it the same pseudo-domain. We continue with the
  1234.      * operation in case the first pathname leaves the pseudo-domain.
  1235.      */
  1236.     request.param.rename.prefixID2.type = -1;
  1237.     } else {
  1238.     pdevHandle2Ptr = ((Fspdev_ClientIOHandle *)prefixHandle2)->pdevHandlePtr;
  1239.     request.param.rename.prefixID2 = pdevHandle2Ptr->userLevelID;
  1240.     }
  1241.     dataPtr = (Fs_2PathData *)malloc(sizeof(Fs_2PathData));
  1242.     (void)strcpy(dataPtr->path1, relativeName1);
  1243.     (void)strcpy(dataPtr->path2, relativeName2);
  1244.  
  1245.     status = FspdevPseudoStream2Path(pdevHandlePtr, &request, dataPtr,
  1246.         name1ErrorPtr, newNameInfoPtrPtr);
  1247.     free((Address)dataPtr);
  1248.     return(status);
  1249. }
  1250.